#include <sys/time.h>
#include <stdio.h>
#include "somb.h"
#include <stdatomic.h>

uint8_t request_response_data[4096*2];

static atomic_int setrequest_count=0;
static struct timeval setrequest_total_timeval = {0};
static struct timeval setrequest_start_time= {0};
static struct timeval setrequest_end_time= {0};

void test_method_service_provider(uint32_t handle,uint32_t ServiceId,void*MthReqData,uint32_t MthReqDataLen)
{
    if((ServiceId == 0x01010000) || (ServiceId == 0x01010001)){

        if(MthReqDataLen > 4096*2)
        {
            printf("MthReqDataLen too large=%d\n", MthReqDataLen);
            return;
        }

        struct timeval *rt = (struct timeval *)request_response_data;
        gettimeofday(rt, NULL);

        i32SOMB_Method_Complete(handle, ServiceId, request_response_data, MthReqDataLen);
    }
    else if(ServiceId == 0x01010002){ //setrequest
        int index = atomic_fetch_add(&setrequest_count,1); 

        if(index == 0)
        {
            memcpy(&setrequest_start_time, MthReqData, sizeof(struct timeval));
        }
        else if(index == 999)
        {
            gettimeofday(&setrequest_end_time,  NULL);

            timersub(&setrequest_end_time, &setrequest_start_time, &setrequest_total_timeval);

            printf("total cost:%ld.%06ld\n", setrequest_total_timeval.tv_sec, setrequest_total_timeval.tv_usec);
            setrequest_count=0;
        }
    }
}
int32_t test_event_on_listen_cb(uint32_t ServiceId,void**EvtData,uint32_t *EvtDataLen)
{
    /*if this function is called, that means some other consumer was listenning to the ServiceId(Event type)*/
    printf("test2 recv Event ServiceId=0x%08x was being listened \n", ServiceId);
    
    /* prepare the memory space for the event data */
    *EvtData = SOMB_ALLOC(32);
    if(NULL == *EvtData)
    {
        printf("### malloc failed\n");
        return SOMB_FAIL;
    }
    memset(*EvtData, 0, 32);

    /* prepare the event data */
    *EvtDataLen = sprintf((char *)*EvtData, "%08x is ready!", ServiceId);

    /*don't free the memory allocated by EvtData if return SOMB_OK, it will auto freed by somb*/
    return SOMB_OK;
}

int32_t deploy_service(void)
{
    void**Instance = NULL;
    int ret;
    Instance = vSOMB_Service_Instance_New();
    if(NULL == Instance)
    {
        printf("new service instance failed");
        return -1;
    }


    ret = i32SOMB_Service_Add(Instance, 0x01010000, SOMB_SVC_TYPE_METHOD,test_method_service_provider); 
    ret = i32SOMB_Service_Add(Instance, 0x01010001, SOMB_SVC_TYPE_METHOD,test_method_service_provider); 
    ret = i32SOMB_Service_Add(Instance, 0x01010002, SOMB_SVC_TYPE_METHOD,test_method_service_provider); 
    ret = i32SOMB_Service_Add(Instance, 0x01010003, SOMB_SVC_TYPE_EVENT,test_event_on_listen_cb); 

    ret = i32SOMB_Service_Instance_Deploy(Instance);
    if(SOMB_OK != ret)
    {
        printf("run throuhgput server somb service deploy failed\n");
        return -1;
    }
    else 
    {
        printf("run throuhgput serversomb service deploy success\n");
    }


    ret = i32SOMB_Service_Instance_Destroy(Instance);
    if(SOMB_OK != ret)
    {
        printf("somb service destory failed\n");
        return -1;
    }

    return 0;
}

void trigger_event_service(void)
{
    uint32_t ServiceId = 0x01010003;

    printf("please event payload length:\n");
    uint32_t length=0;
    scanf("%d", &length);
    printf("payload length=%d\n", length);

    uint8_t *EventData = malloc(length);
    struct timeval *t1 = (struct timeval *)EventData;
    gettimeofday(t1,NULL);

    for(int loop = 0; loop < 1000; loop++)
    {
        int32_t ret = i32SOMB_Event_Trigger(ServiceId, EventData, length);
        if(SOMB_OK != ret)
        {
            printf("trigger event service id(%08x) failed\n", ServiceId);
        }
        else
        {
            //printf("trigger event service id(%08x) success\n", ServiceId);
        }
    }

    free(EventData);

}


void print_usage()
{
    printf("1:deploy service\n");
    printf("2:trigger event service\n");

}
int main(void)
{
    uint32_t SubNsId;
    int32_t ret = i32SOMB_SubNs_Init(&SubNsId);
    if(SOMB_OK != ret)
    {
        printf("%s somb sub ns init failed\n",__FUNCTION__ );
        return -1;
    }
    printf("SubNs=%d SOMB Init success\n",SubNsId);


    while(1)
    {
        print_usage();
        printf("chose your test index:\n");
        int cmd;
        scanf("%d",&cmd);
        printf("your chose is %d \n",cmd);
        switch(cmd)
        {
            case 1: /* deploy service */
                deploy_service();
                break;
            case 2: /* trigger event service */
                trigger_event_service();
                break;
        }
    }

    return 0;
}
